// Copyright 2016 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <lib/unittest/unittest.h>
#include <stddef.h>

#include <fbl/algorithm.h>
#include <fbl/alloc_checker.h>
#include <fbl/inline_array.h>

namespace {

struct TestType {
  TestType() { ctor_run_count++; }

  ~TestType() { dtor_run_count++; }

  static void ResetRunCounts() {
    ctor_run_count = 0u;
    dtor_run_count = 0u;
  }

  static size_t ctor_run_count;
  static size_t dtor_run_count;
};

size_t TestType::ctor_run_count = 0u;
size_t TestType::dtor_run_count = 0u;

bool inline_test() {
  BEGIN_TEST;

  for (size_t sz = 0u; sz <= 3u; sz++) {
    TestType::ResetRunCounts();
    {
      fbl::AllocChecker ac;
      fbl::InlineArray<TestType, 3u> ia(&ac, sz);
      EXPECT_TRUE(ac.check());
    }
    EXPECT_EQ(TestType::ctor_run_count, sz);
    EXPECT_EQ(TestType::dtor_run_count, sz);
  }

  END_TEST;
}

bool non_inline_test() {
  static const size_t test_sizes[] = {4u, 5u, 6u, 10u, 100u, 1000u};

  BEGIN_TEST;

  for (size_t i = 0u; i < fbl::count_of(test_sizes); i++) {
    size_t sz = test_sizes[i];

    TestType::ResetRunCounts();
    {
      fbl::AllocChecker ac;
      fbl::InlineArray<TestType, 3u> ia(&ac, sz);
      EXPECT_TRUE(ac.check());
    }
    EXPECT_EQ(TestType::ctor_run_count, sz);
    EXPECT_EQ(TestType::dtor_run_count, sz);
  }

  END_TEST;
}

}  // namespace

UNITTEST_START_TESTCASE(inline_array_tests)
UNITTEST("inline test", inline_test)
UNITTEST("non-inline test", non_inline_test)
UNITTEST_END_TESTCASE(inline_array_tests, "inlinearraytests", "Inline array test");
